package com.zhou.vo;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.ImmutableSet;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Set;

/**
 * 模仿 framework-boot 返回的 json 对象值 Created by chunlin.qiu on 2017/8/2.
 */
public class RespData extends LinkedHashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    private static final String TIME = "time";

    private static final String CODE = "code";

    private static final String MSG = "msg";

    private static final String DATA = "data";

    private static final Set<String> rejectKeys = ImmutableSet.of(TIME, CODE, MSG, DATA);

    private RespData() {
        this(200);
    }

    private RespData(int code) {
        super(4);
        this.put(TIME, System.currentTimeMillis());
        this.put(CODE, code);
    }

    public RespData set(String key, Object value) {
        Assert.isTrue(!rejectKeys.contains(key), key + ", using its setter method");
        this.put(key, value);
        return this;
    }

    @JsonIgnore
    public int getCode() {
        return (Integer) this.get(CODE);
    }

    @JsonIgnore
    public long getTime() {
        return (Long) this.get(TIME);
    }

    public RespData setMsg(String value) {
        this.put(MSG, value);
        return this;
    }

    @JsonIgnore
    public String getMsg() {
        return (String) this.get(MSG);
    }

    public <T> RespData setData(T data) {
        this.put(DATA, data);
        return this;
    }

    @JsonIgnore
    @SuppressWarnings("unchecked")
    public <T> T getData() {
        return (T) this.get(DATA);
    }

    @Override
    public String toString() {
        return JSON.toJSON(this).toString();
    }

    public static RespData ok() {
        return new RespData();
    }

    /** 返回正常，指定内容，对于 list 内容，请勿使用此方法 */
    public static <T> RespData ok(T data) {
        return ok().setData(data);
    }

    public static <T> RespData ok(int code , T data) {
        return new RespData(code).setData(data);
    }

    /** 返回正常，分页 Collection 内容 */
    public static RespData of(Collection<?> list, long total) {
        return new RespData().setData(new ListData(list, total));
    }

    /** 返回正常，单页 Collection 内容 */
    public static RespData of(Collection<?> list) {
        return of(list, 0);
    }


    /** 返回正常，空分页内容 */
    public static RespData ofEmpty() {
        return of(Collections.emptyList(), 0);
    }

    /** 禁止访问 */
    public static RespData forbidden() {
        return new RespData(HttpStatus.FORBIDDEN.value());
    }

    /** 未授权 */
    public static RespData unAuthorized() {
        return new RespData(HttpStatus.UNAUTHORIZED.value());
    }

    /** 未找到 */
    public static RespData notFound() {
        return new RespData(HttpStatus.NOT_FOUND.value());
    }

    /** 超时 */
    public static RespData timeout() {
        return new RespData(HttpStatus.REQUEST_TIMEOUT.value());
    }

    /** 返回异常 */
    public static RespData ex(String msg) {
        return new RespData(HttpStatus.INTERNAL_SERVER_ERROR.value()).setMsg(msg);
    }

    /** 参数错误 */
    public static RespData bad(String msg) {
        return new RespData(HttpStatus.BAD_REQUEST.value()).setMsg(msg);
    }

    public static RespData ofErr(String msg) {
        return msg == null ? ok() : bad(msg);
    }

    @Getter
    @Setter
    @RequiredArgsConstructor
    public static class ListData {

        private final Collection<?> list;

        private final Long total;
    }
}